const User = require("../db/model/users")
const Question = require("../db/model/questions")
const Answer = require("../db/model/answers")
const jwt = require("jsonwebtoken")
const { secret } = require("../conifig/config")
const { SuccessModel, ErrorModel } = require("../utils/resModel")

class UserCtl {
    /**
     * 查询用户列表
     * @param {*} ctx 
     * @param {*} next 
     */
    async find(ctx, next) {
        const { per_page = 10 } = ctx.query
        const perPage = Math.max(parseInt(per_page), 1)
        const page = Math.max(parseInt(ctx.query.page), 1) - 1
        const user = await User.find({ username: new RegExp(ctx.query.q) }).limit(perPage).skip(page * perPage)
        ctx.body = new SuccessModel(user)
    }

    /**
     * 根据ID查询用户
     * @param {*} ctx 
     * @param {*} next 
     */
    async findById(ctx, next) {
        const { fields = "" } = ctx.query
        const selectFields = fields.split(";").filter(f => f).map(f => " +" + f).join('')
        const populateStr = fields.split(";").filter(f => f).map(f => {
            if (f === "employments") {
                return "employments.company employments.job"
            }
            if (f === "educations") {
                return "educations.school educations.major"
            }
            return f
        }).join(" ")
        const user = await User.findById(ctx.state.user._id).select(selectFields)
            .populate(populateStr)
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user)
    }

    /**
     * 注册一个用户
     * @param {*} ctx 
     * @param {*} next 
     */
    async createUser(ctx, next) {
        ctx.verifyParams({
            username: { type: "string", required: true },
            password: { type: "string", required: true },
            phone: { type: "string", required: true }
        })
        const { username, phone } = ctx.request.body
        const repeatedUser = await User.findOne({ username })
        const repeatedPhone = await User.findOne({ phone })
        if (repeatedUser || repeatedPhone) {
            repeatedUser ? ctx.throw(409, "该用户名已被注册") : ctx.throw(409, "该手机号已经被注册")
        }
        const user = await new User(ctx.request.body).save()
        ctx.body = new SuccessModel(user)
    }

    /**
     * 检查用户是否有操作权限
     * @param {*} ctx 
     * @param {*} next 
     */
    async checkOwner(ctx, next) {
        if (ctx.params.id !== ctx.state.user._id) {
            ctx.throw(403, "没有权限操作")
        }
        await next()
    }

    /**
     * 更新用户信息
     * @param {*} ctx 
     */
    async update(ctx) {
        ctx.verifyParams({
            username: { type: "string", required: false },
            password: { type: "string", required: false },
            phone: { type: "string", required: false },
            avatar_url: { type: "string", required: false },
            gender: { type: "string", required: false },
            headline: { type: "string", required: false },
            locations: { type: "string", required: false },
            business: { type: "string", required: false },
            employments: { type: "array", itemType: "object", required: false },
            educations: { type: "array", itemType: "object", required: false },
        })
        const user = await User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user)
    }

    /**
     * 删除用户
     * @param {*} ctx 
     */
    async deleteUser(ctx) {
        const user = await User.findByIdAndRemove(ctx.params.id)
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user)
    }

    /**
     * 用户登录
     * @param {*} ctx 
     */
    async login(ctx) {
        ctx.verifyParams({
            username: { type: "string", required: true },
            password: { type: "string", required: true }
        })
        const user = await User.findOne(ctx.request.body)
        if (!user) {
            ctx.throw(401, "用户名或密码错误")
        }
        const { _id, username } = user
        const token = jwt.sign({ _id, username }, secret, { expiresIn: '1d' })
        ctx.body = new SuccessModel({ token })
    }

    /**
     * 获取用户关注列表
     * @param {*} ctx 
     */
    async listFollowing(ctx) {
        const user = await User.findById(ctx.params.id).select("+following").populate("following")
        if (!user) {
            ctx.throw(404, "关注用户列表不存在")
        }
        ctx.body = new SuccessModel(user.following)
    }

    /**
     * 检测用户是否存在
     * @param {*} ctx 
     * @param {*} next 
     */
    async checkUserExist(ctx, next) {
        const user = await User.findById(ctx.params.id)
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        await next()
    }

    /**
     * 关注某人
     * @param {*} ctx 
     */
    async follow(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+following")
        if (!me.following.map(id => id.toString()).includes(ctx.params.id)) {
            me.following.push(ctx.params.id)
            me.save()
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("已关注了该用户")
        }
    }

    /**
     * 取消关注
     * @param {*} ctx 
     */
    async unFollow(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+following")
        const index = me.following.map(id => id.toString()).indexOf(ctx.params.id)
        if (index > -1) {
            me.following.splice(index, 1)
            me.save()
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("您尚未关注该用户")
        }
    }

    /**
     * 获取粉丝列表
     * @param {*} ctx 
     */
    async listFollowers(ctx) {
        const users = await User.find({ following: ctx.params.id })
        ctx.body = new SuccessModel(users)
    }

    /**
     * 用户关注的话题列表
     * @param {*} ctx 
     */
    async listFollowingTopic(ctx) {
        const user = await User.findById(ctx.params.id).select("+followingTopics").populate("followingTopics")
        if (!user) {
            ctx.throw(404, "关注话题列表不存在")
        }
        ctx.body = new SuccessModel(user.followingTopics)
    }

    /**
    * 关注话题
    * @param {*} ctx 
    */
    async followTopic(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+followingTopics")
        if (!me.followingTopics.map(id => id.toString()).includes(ctx.params.id)) {
            me.followingTopics.push(ctx.params.id)
            me.save()
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("已关注了该用户")
        }
    }

    /**
     * 取消关注话题
     * @param {*} ctx 
     */
    async unFollowTopic(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+followingTopics")
        const index = me.followingTopics.map(id => id.toString()).indexOf(ctx.params.id)
        if (index > -1) {
            me.followingTopics.splice(index, 1)
            me.save()
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("您尚未关注该话题")
        }
    }

    /**
     * 查询用户的问题列表
     * @param {*} ctx 
     */
    async listQuestions(ctx) {
        const { per_page = 10 } = ctx.query
        const perPage = Math.max(parseInt(per_page), 1)
        const page = Math.max(parseInt(ctx.query.page), 1) - 1
        const questions = await Question.find({ questioner: ctx.params.id }).limit(perPage).skip(page * perPage)
        ctx.body = new SuccessModel(questions)
    }


    /**
     * 赞回答的列表
     * @param {*} ctx 
     */
    async listLikingAnswers(ctx) {
        const user = await User.findById(ctx.params.id).select("+likingAnswers").populate("likingAnswers")
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user.likingAnswers)
    }

    /**
    * 赞一个回答
    * @param {*} ctx 
    */
    async likingAnswer(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select("+likingAnswers")
        if (!me.likingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
            me.likingAnswers.push(ctx.params.id)
            me.save()
            await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: 1 } })
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("已赞了该回答")
        }
        await next()
    }

    /**
     * 取消赞一个回答
     * @param {*} ctx 
     */
    async unlikingAnswer(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+likingAnswers")
        const index = me.likingAnswers.map(id => id.toString()).indexOf(ctx.params.id)
        if (index > -1) {
            me.likingAnswers.splice(index, 1)
            me.save()
            await Answer.findByIdAndUpdate(ctx.params.id, { $inc: { voteCount: -1 } })
            ctx.body = new SuccessModel()
        }
    }

    /**
    * 踩回答的列表
    * @param {*} ctx 
    */
    async listDislikingAnswers(ctx) {
        const user = await User.findById(ctx.params.id).select("+dislikingAnswers").populate("dislikingAnswers")
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user.dislikingAnswers)
    }

    /**
    * 踩一个回答
    * @param {*} ctx 
    */
    async dislikingAnswer(ctx, next) {
        const me = await User.findById(ctx.state.user._id).select("+dislikingAnswers")
        if (!me.dislikingAnswers.map(id => id.toString()).includes(ctx.params.id)) {
            me.dislikingAnswers.push(ctx.params.id)
            me.save()
            ctx.body = new SuccessModel()
        } else {
            ctx.body = new ErrorModel("已踩了该回答")
        }
        await next()
    }

    /**
     * 取消踩一个回答
     * @param {*} ctx 
     */
    async undislikingAnswer(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+dislikingAnswers")
        const index = me.dislikingAnswers.map(id => id.toString()).indexOf(ctx.params.id)
        if (index > -1) {
            me.dislikingAnswers.splice(index, 1)
            me.save()
            ctx.body = new SuccessModel()
        }
    }


    /**
    * 收藏的回答的列表
    * @param {*} ctx 
    */
    async listCollectingQuestions(ctx) {
        const user = await User.findById(ctx.params.id).select("+collectingQuestions").populate("collectingQuestions")
        if (!user) {
            ctx.throw(404, "用户不存在")
        }
        ctx.body = new SuccessModel(user.collectingQuestions)
    }

    /**
    * 收藏一个问题
    * @param {*} ctx 
    */
    async collectingQuestion(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+collectingQuestions")
        if (!me.collectingQuestions.map(id => id.toString()).includes(ctx.params.id)) {
            me.collectingQuestions.push(ctx.params.id)
            const question = me.save()
            ctx.body = new SuccessModel(question)
        } else {
            ctx.body = new ErrorModel("已收藏该问题")
        }
    }

    /**
     * 取消收藏一个问题
     * @param {*} ctx 
     */
    async uncollectingQuestion(ctx) {
        const me = await User.findById(ctx.state.user._id).select("+collectingQuestions")
        const index = me.collectingQuestions.map(id => id.toString()).indexOf(ctx.params.id)
        if (index > -1) {
            me.collectingQuestions.splice(index, 1)
            me.save()
            ctx.body = new SuccessModel()
        }
    }
}



module.exports = new UserCtl()